今天的一開始先花一點點時間,把昨天的事件監聽做完吧!這邊準備好一個基本的介面:
Css就不做教學了XD,大家用自己喜歡的樣式唄
<ul>
<li><button id="Play">Play</button></li>
<li><button id="Pause">Pause</button></li>
<li>
<select id="Select">
<option>- 請選擇曲名 -</option>
<option value="Advertime.mp3">Advertime</option>
</select>
</li>
<li><button id="Upload-beautify">- 上傳音樂 -</button></li>
<input hidden id="Upload" type="file" value="- 上傳音樂 -" accept="audio/*">
</ul>
<audio id="Music" controls>
<source src="../music/Lovely Piano Song.mp3">
</audio>
依序為昨天沒做完的Play、Pause、Select加上事件監聽:
let audio = document.querySelector("#Music");
let Play = document.querySelector("#Play");
let Pause = document.querySelector("#Pause");
Play.addEventListener("click", audioControl, false);
Pause.addEventListener("click", audioControl, false);
let audioControl = function(){
// 取得該元件ID的值
let ID = this.attributes.id.nodeValue; // 'Play' or 'Pause'
if(ID == "Play") audio.play();
else audio.pause();
}
Select.addEventListener("change", function(){
audio.src = "../music/" + this.value;
}, false);
這邊透過共用audioControl函式,就可以統一控制播放和暫停會用到的代碼,預期未來可能會有共用的程式碼。
是不是很簡單呢?其實會放到今天才講,除了讓昨天專注把最複雜的上傳做完之外,也是因為原本我把頻譜分析也放在Play裡面,剛好今天一起講解,不過後來想想,拆開來對大家來說比較乾淨好懂。
接下來在搞音樂前,要先做canvas的基本設定和觀念釐清
觀念真的很重要!相信我,學懂了之後可以避免未來debug到瘋掉,
<canvas id="canvas"></canvas>
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let x = 5, y = 5; // 待會範例使用
這個在習慣上會被簡稱context的物件,有著許多用來畫圖的方法,在現實中,畫圖一般都會先用鉛筆或不顯眼的顏色做底稿,才會真正開始描邊跟著色,Canvas的操作邏輯也很相似且直覺,以「畫黑色的正方形」的三個階段做舉例:
context.beginPath(); // 準備好新的畫筆
context.moveTo(x, y); // 畫筆不碰到畫布的前提下,移動到(x, y)處放下畫筆
context.lineTo(x + 10, y); // 將畫筆從現在/最後位置(x, y)移動到(x + 10, y),在畫布上留下一段路徑
context.lineTo(x + 10, y + 10);
context.lineTo(x, y + 10);
context.closePath(); // 從最後的位置(x, y + 10)移動到開始的(x, y),留下路徑
closePath實務上較少使用,也容易被混淆,其實不一定要使用,並且可以用context.lineTo(x, y)來替代
context.fillStyle = 'rgb(0,0,0)'; // 設定填滿顏色為黑色
context.lineWidth = 1; // 設定線段
context.strokeStyle = 'black'; // 設定邊框顏色為黑色
context.fill(); // 著色(剛剛的正方形填滿)
context.stroke(); // 描邊(剛剛的正方形邊框)
應該不難理解,如果少了任何一個階段,就沒辦法成功的把圖畫出來;如果只畫了草稿(路徑),忘了上色,就不會有圖案;如果沒有設定顏色,就直接上色,就像水彩筆沒有沾顏料一樣。
好消息是,當你了解這一個Canvas繪圖的邏輯之後,就不一定每次都要經過這麼完整的步驟了,像是現實中顏料只需要準備一次就好,就可以一直畫直到用完,在Canvas也一樣,只是顏料永遠不會用完,因此如果要連續繪製相同顏色的圖形,就不用每次都重新設定,值得一提的是,能設定的東西相當豐富,除了上面所列出的,還有線條樣式、文字樣式、陰影,等等五花八門,若有用到再跟大家說明吧!
可能有人會想,我畫個正方形就要寫這麼多行,好累呀!其實,除了自己手刻函數之外,還真的有很方便的原生API可以用唷!跟上面一模一樣的操作,只需要寫下短短幾行:
context.fillRect(x, y, 10, 10); // 左上角(x, y)為起點,將一個長10寬10的矩形填滿
context.strokeRect(x, y, 10, 10); // 左上角(x, y)為起點,將一個長10寬10的矩形邊框
這兩個函式,實際上幫你把上述提到的幾個必要步驟都包進來了,加上這邊沿用剛剛已設定過的黑色(填滿跟邊框),就能夠如此的簡化,算是新手一大福音,搭配滑鼠游標事件,就可以很輕鬆地做出像是繪圖軟體中的矩形工具,不過這不是本次的主題XD,就不特別實作了,我們的重點可是音樂呀!
不過聰明的你,是否發現了?上面這兩行代碼看起來簡潔,其實重複做了同一件事兩次!它們各自經歷了路徑階段+上色階段,而兩個矩形都是一模一樣的正方形,因此相比最一開始看起來"複雜"的例子,很有可能花費更多時間,這是一個值得思考的點,若未來需要畫上百上千個矩形,又同時有填滿+邊框的效果(也許不同顏色),那是不是自己寫一個function或用長一點的代碼,更能夠優化效能呢?這就留給大家思考了。
今天剩下的時間也不多,只好明天繼續了!
話說...我其實給大家準備demo拉XD,但沒想到寫文章這麼花時間呀~~~沒辦法衝到我想要的進度,大家就先體驗一下音頻圖像化的魅力吧!(ps: 可以上傳自己喜歡的音樂唷)
請想想看,如果給了你長度為1024一個陣列,每筆資料則是介於0~255之間,要怎麼用今天教的方法,畫出像Demo那樣的直方圖呢?你覺得可以設置和調整的參數有什麼?歡迎大家留言回答